package com.whzjkj.gateway.server.codce;

import com.whzjkj.gateway.util.BCD8421Utils;
import com.whzjkj.gateway.util.ByteUtils;
import com.whzjkj.gateway.vo.PackageData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * @description: JT808消息解码
 * @author: Mr.Hu
 * @create: 2018-10-31 15:12
 **/
@Component
@Slf4j
public class JT808MessageDecoder {

    /**
     * 解析消息
     * 7E0200003A014530929922072E0000000000000003015823BE06CAC8980000018600AC181030184251010400001744EB16000C00B2898607B619179297358200060089FFFFFFFF977E
     * 7E                             -- 标识位
     *
     * 0200 003A 0145 3092 9922 072E [0000] -- 消息头
     * 0200                                 -- 消息ID
     *      003A                            -- 消息体属性
     * 	         0145 3092 9922             -- 终端手机号
     * 		                    072E        -- 消息流水号
     * 		                          0000  -- 消息包封装项（根据消息体属性中的分包标识确定消息分包，不分包则无该项）
     * 	    003A
     *        V
     *      0000 0000 0011 1010       -- 消息体属性
     * 		       00 0011 1010       -- 消息体长度 58
     * 		   0 00                   -- 数据加密方式
     * 	      0                       -- 分包
     *      00                        -- 保留
     *
     * 000000000003015823BE06CAC8980000018600AC181030184251010400001744EB16000C00B2898607B619179297358200060089FFFFFFFF 97
     *
     * 97 -- 校验码（从消息头开始，同后一字节异或，直到校验码前一个字节）
     *
     * 7E -- 标识位
     * @param msg
     * @return
     */
    public PackageData byte2PackageData(byte[] msg){
        PackageData pkgData = new PackageData();
        //设置包头信息
        PackageData.MessageHeader messageHeader = parseMessageHander(msg);
        pkgData.setMessageHeader(messageHeader);
        //消息体起始位置
        int messageBodyStartIndex = 12;
        if (messageHeader.isHasSubPackage()){
            messageBodyStartIndex = 16;
        }
        byte[] messageBody = new byte[messageHeader.getMessageBodyLength()];
        System.arraycopy(msg, messageBodyStartIndex, messageBody, 0, messageBody.length);
        pkgData.setMessageBodyBytes(messageBody);
        //校验码为去掉标识位后的最后一位
        int checkCode = msg[msg.length-1];
        //从消息头开始，同后一字节异或，直到校验码前一个字节
        int mathCheckCode = ByteUtils.mathCheckCode(msg, 0, msg.length-1);
        pkgData.setCheckCode(checkCode);
        if (checkCode!=mathCheckCode){
            log.error("校验码不一致");
        }
        return pkgData;
    }

    /**
     * 解析消息头
     * @param data
     * @return
     */
    private PackageData.MessageHeader parseMessageHander(byte[] data){
        PackageData.MessageHeader messageHeader = new PackageData.MessageHeader();
        // 80 01 00 05 01 45 30 92 99 22 07 2E 07 2E 02 00 00 DB
        // 消息头word(16) 双字节整形
        // 消息ID [0-1]
        int messageId = this.parseIntFromBytes(data, 0, 2);
        messageHeader.setMessageId(messageId);
        // 消息体属性 [2-3]
        int messageBodyProperty = this.parseIntFromBytes(data,2, 2);
        messageHeader.setMessageBodyProperty(messageBodyProperty);
        // [ 0-9 ] 0000,0011,1111,1111(0x3FF)(消息体长度)
        messageHeader.setMessageBodyLength(messageBodyProperty & 0x3ff);
        // [10-12] 0001,1100,0000,0000(0x1C00)(加密类型)
        messageHeader.setEncryptionType((messageBodyProperty & 0x1c00) >> 10);
        // [ 13_ ] 0010,0000,0000,0000(0x2000)(是否有子包)
        messageHeader.setHasSubPackage(((messageBodyProperty & 0x2000) >> 13)==1);
        // [14-15] 1100,0000,0000,0000(0xC000)(保留位)
        messageHeader.setReservedBit(((messageBodyProperty & 0xc000) >> 14)+"");
        // 终端手机号 BCD[6] 4-9
        String terminalPhone = this.parseStringFromBCDBytes(data,4,6);
        messageHeader.setTerminalPhone(terminalPhone);
        // 消息流水号
        int messageFlowNo = this.parseIntFromBytes(data,10,2);
        messageHeader.setMessageFlowNo(messageFlowNo);
        if (messageHeader.isHasSubPackage()){
            // 消息包封装项字段
            messageHeader.setPackageInfoFild(this.parseIntFromBytes(data, 12, 4));
            // 消息包总数byte[0-1]
            messageHeader.setTotalSubPackage(this.parseIntFromBytes(data, 12, 2));
            // byte[2-3] 包序号(word(16)) 从 1 开始
            messageHeader.setSubPackageSeq(this.parseIntFromBytes(data, 12, 2));
        }
        return messageHeader;
    }



    private String parseStringFromBCDBytes(byte[] data, int startIndex, int length) {
        return parseStringFromBCDBytes(data, startIndex, length, null);
    }

    private String parseStringFromBCDBytes(byte[] data, int startIndex, int length, String defaultVal) {
        try {
            byte[] tmp = new byte[length];
            System.arraycopy(data, startIndex, tmp, 0, length);
            return BCD8421Utils.bcd2String(tmp);
        }catch (Exception e){
            e.printStackTrace();
            return defaultVal;
        }
    }

    private static int parseIntFromBytes(byte[] data, int startIndex, int length) {
        return parseIntFromBytes(data, startIndex, length, 0);
    }

    private static int parseIntFromBytes(byte[] data, int startIndex, int length, int defaultVal) {
        try {
            // 字节数大于4,从起始索引开始向后处理4个字节,其余超出部分丢弃
            final int len = length > 4 ? 4 : length;
            byte[] tmp = new byte[len];
            System.arraycopy(data, startIndex, tmp, 0, len);
            return ByteUtils.byteToInteger(tmp);
        }catch (Exception e){
            e.printStackTrace();
            return defaultVal;
        }
    }
}
